package fi.foyt.cs.oauth.provider.data;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.restlet.ext.oauth.provider.data.Token;

import fi.foyt.cs.controller.OAuthController;
import fi.foyt.cs.persistence.domainmodel.oauth.AuthenticatedUser;
import fi.foyt.cs.persistence.domainmodel.oauth.AuthenticatedUserCode;

public class GAEAuthenticatedUser implements org.restlet.ext.oauth.provider.data.AuthenticatedUser {

  public GAEAuthenticatedUser(String id) {
    this.id = id;
  }
  
  @Override
  public String getId() {
    return id;
  }

  @Override
  public void addCode(String code) {
    OAuthController oAuthController = new OAuthController();
    AuthenticatedUser AuthenticatedUser = oAuthController.findAuthenticatedUserByUserId(getId()); 
    oAuthController.createAuthenticatedUserCode(AuthenticatedUser, code);
  }

  @Override
  public void removeCode(String code) {
    OAuthController oAuthController = new OAuthController();
    AuthenticatedUser AuthenticatedUser = oAuthController.findAuthenticatedUserByUserId(getId()); 
    AuthenticatedUserCode AuthenticatedUserCode = oAuthController.findAuthenticatedUserCodeByAuthenticatedUserAndCode(AuthenticatedUser, code);
    oAuthController.deleteAuthenticatedUserCode(AuthenticatedUserCode);
  }

  @Override
  public void addScope(String scope, String owner) {
    // TODO: owner
    OAuthController oAuthController = new OAuthController();
    AuthenticatedUser AuthenticatedUser = oAuthController.findAuthenticatedUserByUserId(getId());
    Set<String> grantedScopes = getGrantedScopesAsSet(AuthenticatedUser);
    grantedScopes.add(scope);
    oAuthController.updateAuthenticatedUserGrantedScopes(AuthenticatedUser, getGrantedScopseAsString(grantedScopes));
  }

  @Override
  public boolean isGrantedScope(String scope, String owner) {
    // TODO: owner
    OAuthController oAuthController = new OAuthController();
    AuthenticatedUser AuthenticatedUser = oAuthController.findAuthenticatedUserByUserId(getId());
    Set<String> grantedScopes = getGrantedScopesAsSet(AuthenticatedUser);
    return grantedScopes.contains(scope);
  }

  @Override
  public void revokeScope(String scope, String owner) {
    OAuthController oAuthController = new OAuthController();
    AuthenticatedUser AuthenticatedUser = oAuthController.findAuthenticatedUserByUserId(getId());
    Set<String> grantedScopes = getGrantedScopesAsSet(AuthenticatedUser);
    grantedScopes.remove(scope);
    oAuthController.updateAuthenticatedUserGrantedScopes(AuthenticatedUser, getGrantedScopseAsString(grantedScopes));
  }

  @Override
  public String[] getGrantedScopes() {
    OAuthController oAuthController = new OAuthController();
    AuthenticatedUser AuthenticatedUser = oAuthController.findAuthenticatedUserByUserId(getId());
    Set<String> grantedScopes = getGrantedScopesAsSet(AuthenticatedUser);
    return grantedScopes.toArray(new String[0]);
  }

  @Override
  public long getTokenExpire() {
    return Token.UNLIMITED;
  }

  @Override
  public void setTokenExpire(long deltaTimeSec) {
  }

  @Override
  public void revokeScopes() {
    OAuthController oAuthController = new OAuthController();
    AuthenticatedUser AuthenticatedUser = oAuthController.findAuthenticatedUserByUserId(getId());
    oAuthController.updateAuthenticatedUserGrantedScopes(AuthenticatedUser, "");
  }

  private Set<String> getGrantedScopesAsSet(AuthenticatedUser AuthenticatedUser) {
    String grantedScopesString = AuthenticatedUser.getGrantedScopes();
    if (!StringUtils.isBlank(grantedScopesString)) {
      return new HashSet<String>(Arrays.asList(grantedScopesString.split(",")));
    } else {
      return new HashSet<String>();
    }
  }
  
  private String getGrantedScopseAsString(Set<String> grantedScopes) {
    StringBuilder result = new StringBuilder();
    Iterator<String> iterator = grantedScopes.iterator();
    while (iterator.hasNext()) {
      result.append(iterator.next());
      if (iterator.hasNext()) {
        result.append(',');
      }
    }
    return result.toString();
  }
  
  private String id;
}
